package com.zy.db.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.CaseFormat;
import com.zy.db.enums.QueryTypeEnums;
import com.zy.db.pointcut.Q;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;

@Slf4j
public class QueryUtils<T> {


    public static QueryWrapper<?> getParam(QueryWrapper<?> queryWrapper, Object dto, Class<?> cla) {
        JSONObject json = (JSONObject) JSONObject.toJSON(dto);
        for (Field declaredField : cla.getDeclaredFields()) {
            if (!valid(declaredField, json)) {
                continue;
            }
            Object value = getValue(json, declaredField);

            setQueryTypeEnums(queryWrapper, declaredField, value);
            setOrderBy(queryWrapper, declaredField);
        }
        return queryWrapper;
    }

    public static QueryWrapper<?> getOneParam(QueryWrapper<?> queryWrapper, Object dto, Class<?> cla) {
        return getOneParam(queryWrapper, dto, cla).last("LIMIT 1");
    }


    private static Object getValue(JSONObject json, Field field) {
        Object value = json.get(field.getName());
        return ObjectUtils.isEmpty(value) ? field.getAnnotation(Q.class).defaultValue() : value;
    }

    private static String getLowName(Field field) {
        String lowName = StringUtils.isNotBlank(field.getAnnotation(Q.class).key()) ? field.getAnnotation(Q.class).key() : field.getName();
        return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, lowName);
    }

    private static void setQueryTypeEnums(QueryWrapper<?> queryWrapper, Field field, Object value) {
        String lowName = getLowName(field);
        String type = field.getAnnotation(Q.class).value().name();

        if (QueryTypeEnums.deful.name().equals(type)) {
            return;
        }
        if (QueryTypeEnums.eq.name().equals(type)) {
            queryWrapper.eq(lowName, value);
        }
        if (QueryTypeEnums.in.name().equals(type)) {
            queryWrapper.in(lowName, value);
        }
        if (QueryTypeEnums.like.name().equals(type)) {
            queryWrapper.like(lowName, value);
        }
        if (QueryTypeEnums.le.name().equals(type)) {
            queryWrapper.le(lowName, value);
        }
        if (QueryTypeEnums.lt.name().equals(type)) {
            queryWrapper.lt(lowName, value);
        }
        if (QueryTypeEnums.ge.name().equals(type)) {
            queryWrapper.ge(lowName, value);
        }
        if (QueryTypeEnums.gt.name().equals(type)) {
            queryWrapper.gt(lowName, value);
        }
        if (QueryTypeEnums.between.name().equals(type)) {
            JSONArray obj = (JSONArray) value;
            queryWrapper.between(lowName, obj.get(0), obj.get(1));
        }
        if (QueryTypeEnums.gelt.name().equals(type)) {
            JSONArray obj = (JSONArray) value;
            queryWrapper.ge(lowName, obj.get(0));
            queryWrapper.lt(lowName, obj.get(1));
        }
    }

    private static void setOrderBy(QueryWrapper<?> queryWrapper, Field field) {
        QueryTypeEnums type = field.getAnnotation(Q.class).sort();
        String lowName = getLowName(field);
        if (QueryTypeEnums.asc.equals(type)) {
            queryWrapper.orderByAsc(lowName);
        }
        if (QueryTypeEnums.desc.equals(type)) {
            queryWrapper.orderByDesc(lowName);
        }
    }


    private static Boolean valid(Field declaredField, JSONObject json) {
        Q aa = declaredField.getAnnotation(Q.class);
        if (aa == null) {
            return false;
        }
        if (ObjectUtils.isEmpty(json.get(declaredField.getName()))
                && StringUtils.isBlank(declaredField.getAnnotation(Q.class).defaultValue())
                && QueryTypeEnums.deful == declaredField.getAnnotation(Q.class).sort()) {
            return false;
        }
        return true;
    }

}